package com.nfha.algorithm.geo.crossline;

import java.awt.Point;
import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ThreadPoolExecutor;

import com.nfha.algorithm.Exerciser;
import com.nfha.algorithm.util.Logger;

public class CrosslineExerciser extends Exerciser{

	    
	    public CrosslineExerciser(int nThreads) {
	    	
	    	super(nThreads);
	    }
	
	
	   /*
	    *   line   划出的线
	    *   points  各个条船的点集合
	    *   
	    *   返回 符合经过的路线结果
	    */
	   public List<CrosslineResult> exec(GeoLine line, List<GeoShipPoint> points) throws Exception {
		   
		   List<CrosslineResult> ret=new ArrayList<>();
		   
		   Map<String,List<GeoShipPoint>> sortedPointsMap=new HashMap<>();
		   
		   for(int i=0;i<points.size();i++) {
			   GeoShipPoint point=points.get(i);
			   String key=point.imo;
			   if(key==null||key.trim().length()==0) {
				   throw new Exception("imo号不能为空");
			   }
			   List<GeoShipPoint> sortedPoints=sortedPointsMap.get(key);
			   
			   if(sortedPoints==null) {
				   sortedPoints=new ArrayList<>();
				   sortedPointsMap.put(key, sortedPoints);
			   }
			   sortedPoints.add(point);
			   
		   }
		   
		   
		   List<FutureTask<CrosslineResult>> ftasks=new ArrayList<>();
		   
		   for(Entry<String,List<GeoShipPoint>> en : sortedPointsMap.entrySet()) {
			   
			   String key=en.getKey();
			   List<GeoShipPoint> sortedPoints=en.getValue();
			   
			   sortedPoints.sort(new Comparator<GeoShipPoint>(){

				@Override
				public int compare(GeoShipPoint o1, GeoShipPoint o2) {
					// TODO Auto-generated method stub

					return o1.arrivalAt>=o2.arrivalAt?1:-1;
				}});
			   
			   logger.debug("开始计算:",key," 点总数:",sortedPoints.size());
			   
			   ExecCallback callback=new ExecCallback(line,sortedPoints);
			   
		       FutureTask<CrosslineResult> ftask=new FutureTask<>(callback);
			   ftasks.add(ftask);
			   execute(ftask);
			          
		   }
		   
		   
		   
		   for(FutureTask<CrosslineResult> ftask : ftasks) {
			   
			   CrosslineResult cr=ftask.get();
			   if(cr!=null) {
				   ret.add(cr);
				   
			   }
			   
		   }
		   
		   
		   return ret;
		   
	   }
	
	   
	   


	protected class ExecCallback implements Callable<CrosslineResult>{

		   
		List<GeoShipPoint> sortedPoints;
		   
		GeoLine line0;   
		   
		public ExecCallback(GeoLine line0,List<GeoShipPoint> points) {
			super();
			this.sortedPoints = points;
			this.line0=line0;
		}



		



		@Override
		public CrosslineResult call() throws Exception {
			// TODO Auto-generated method stub
			CrosslineResult ret=null;
			logger.debug("切割线:",line0);
			for(int i=0,j=1;j<sortedPoints.size();i++,j++) {
				
				GeoShipPoint pointi=sortedPoints.get(i)
						,pointj=sortedPoints.get(j)
						;
				
				GeoLine line1=new GeoLine(pointi, pointj);
				
				
				//logger.debug(pointi);
				//logger.debug(pointj);
				
				logger.debug(line1);
				
				int re= segIntersect(line0, line1);
				
				if(re>0) {
					ret=new CrosslineResult(pointi.imo, line1,  pointj.arrivalAt);
					break;
				}
				
				//logger.debug("结果:",re);
				
			}
			return ret;
		}
		   
	   }
	   
	   
	   private static int segIntersect(GeoLine line0,GeoLine line1) {
		   int ret=0;
		   ret=segIntersect(line0.start_point, line0.end_point, line1.start_point, line1.end_point);
		   return ret;
	   } 
	   
	   
	   
	   private static int segIntersect(Point A, Point B, Point C, Point D) {
		   Point intersection = new Point();

		   if (Math.abs(B.getY() - A.getY()) + Math.abs(B.getX() - A.getX()) + Math.abs(D.getY() - C.getY())
		     + Math.abs(D.getX() - C.getX()) == 0) {
		    if ((C.getX() - A.getX()) + (C.getY() - A.getY()) == 0) {
		     System.out.println("ABCD是同一个点！");
		    } else {
		     System.out.println("AB是一个点，CD是一个点，且AC不同！");
		    }
		    return 0;
		   }

		   if (Math.abs(B.getY() - A.getY()) + Math.abs(B.getX() - A.getX()) == 0) {
		    if ((A.getX() - D.getX()) * (C.getY() - D.getY()) - (A.getY() - D.getY()) * (C.getX() - D.getX()) == 0) {
		     System.out.println("A、B是一个点，且在CD线段上！");
		    } else {
		     System.out.println("A、B是一个点，且不在CD线段上！");
		    }
		    return 0;
		   }
		   if (Math.abs(D.getY() - C.getY()) + Math.abs(D.getX() - C.getX()) == 0) {
		    if ((D.getX() - B.getX()) * (A.getY() - B.getY()) - (D.getY() - B.getY()) * (A.getX() - B.getX()) == 0) {
		     System.out.println("C、D是一个点，且在AB线段上！");
		    } else {
		     System.out.println("C、D是一个点，且不在AB线段上！");
		    }
		    return 0;
		   }

		   if ((B.getY() - A.getY()) * (C.getX() - D.getX()) - (B.getX() - A.getX()) * (C.getY() - D.getY()) == 0) {
		 //   System.out.println("线段平行，无交点！");
		    return 0;
		   }

		   double x=((B.getX() - A.getX()) * (C.getX() - D.getX())
			       * (C.getY() - A.getY()) - C.getX()
			       * (B.getX() - A.getX()) * (C.getY() - D.getY()) + A
			       .getX() * (B.getY() - A.getY()) * (C.getX() - D.getX()))
			       / ((B.getY() - A.getY()) * (C.getX() - D.getX()) - (B
			         .getX() - A.getX()) * (C.getY() - D.getY()))
			       ,
			       y=((B.getY() - A.getY()) * (C.getY() - D.getY())
					       * (C.getX() - A.getX()) - C.getY()
					       * (B.getY() - A.getY()) * (C.getX() - D.getX()) + A
					       .getY() * (B.getX() - A.getX()) * (C.getY() - D.getY()))
					       / ((B.getX() - A.getX()) * (C.getY() - D.getY()) - (B
					         .getY() - A.getY()) * (C.getX() - D.getX()))
			       ;
		   
           intersection.setLocation(x, y);
		  

		   if ((intersection.getX() - A.getX()) * (intersection.getX() - B.getX()) <= 0
		     && (intersection.getX() - C.getX())
		       * (intersection.getX() - D.getX()) <= 0
		     && (intersection.getY() - A.getY())
		       * (intersection.getY() - B.getY()) <= 0
		     && (intersection.getY() - C.getY())
		       * (intersection.getY() - D.getY()) <= 0) {

		   if(  (A.getX() == C.getX() && A.getY() == C.getY() ) || ( A.getX() == D.getX() && A.getY() == D.getY() )
		     || (B.getX() == C.getX() && B.getY() == C.getY() ) || ( B.getX() == D.getX() && B.getY() == D.getY() )){
		    
		     System.out.println("线段相交于端点上");
		     return 2;
		    
		    }else {
		     System.out.println("线段相交于点(" + intersection.getX() + ","
		      + intersection.getY() + ")！");
		     return 1; // '相交
		    }
		    
		   } else {
		 //   System.out.println("线段相交于虚交点(" + intersection.getX() + ","
//		      + intersection.getY() + ")！");
		    return -1; // '相交但不在线段上
		   }

		  }


	

	
	   
	
}
